package com.yanfan.energy.service.impl;

import com.yanfan.common.core.domain.AjaxResult;
import com.yanfan.common.core.domain.entity.SysDictData;
import com.yanfan.common.utils.DictUtils;
import com.yanfan.common.utils.SecurityUtils;
import com.yanfan.energy.domain.Consumables;
import com.yanfan.energy.domain.EquipmentConsumptionDto;
import com.yanfan.energy.domain.vo.ConsumablesVo;
import com.yanfan.energy.domain.vo.EnergyFlowVo;
import com.yanfan.energy.mapper.ConsumablesMapper;
import com.yanfan.energy.service.ConsumablesService;
import com.yanfan.energy.util.DateUtils;
import com.yanfan.iot.domain.vo.CakeVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Slf4j
@Service
public class ConsumablesServiceImpl implements ConsumablesService {

    @Autowired
    private ConsumablesMapper consumablesMapper;

    @Override
    public AjaxResult getConsumableShuJuQuShi(Consumables consumables) {
        AjaxResult ajaxResult = new AjaxResult();
        //获取定义配置数据
        List<Consumables> consumablesList = consumablesMapper.selectConfiguration(consumables);
        //获取设备id
        List<Long> collect = consumablesList.stream().filter(item -> item.getDeviceId() != null).map(Consumables::getDeviceId).distinct().collect(Collectors.toList());
        if (collect.isEmpty()) {
            return null;
        }
        if (consumables != null && consumables.getEnd() != null) {
            // 月
            if (consumables.getDateType().equals(2)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(consumables.getEnd());
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH) + 1;
                consumables.setEnd(DateUtils.getLastDayOfMonth(year, month));
            }
            consumables.setEnd(DateUtils.changeTheEnd(consumables.getEnd()));
        } else {
            setTimeDimensionDate(consumables);
        }
        //获取设备能源数据
        List<EquipmentConsumptionDto> equipmentConsumption = consumablesMapper.getEquipmentConsumption(consumables, collect);

        //获取时间
        List<Integer> dates = new ArrayList<>();
        if(consumables.getDateType().equals("1")){
            dates= IntStream.range(1, 25).boxed().collect(Collectors.toList());
        }
        if(consumables.getDateType().equals("2")){
            dates= IntStream.range(1, 32).boxed().collect(Collectors.toList());
        }
        if(consumables.getDateType().equals("3")){
            dates= IntStream.range(1, 13).boxed().collect(Collectors.toList());
        }
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        //统计电
        Map<Integer,Double> dian = new HashMap<>();
        Map<Integer, Double> collectDian = getCollects(equipmentConsumption,formatter,2,consumables.getDateType());
        processVoltageAndCurrentShui(dates,dian,collectDian);
        List<Double> d = new ArrayList<>(dian.values());
        ajaxResult.put("d",d.stream()
                .map(value -> new BigDecimal(value)
                        .setScale(4, RoundingMode.HALF_UP)
                        .doubleValue())
                .collect(Collectors.toList()));
        //统计水
        Map<Integer,Double> shui = new HashMap<>();
        Map<Integer, Double> collectShui = getCollects(equipmentConsumption,formatter,1,consumables.getDateType());
        processVoltageAndCurrentShui(dates,shui,collectShui);
        List<Double> s = new ArrayList<>(shui.values());
        ajaxResult.put("s",s.stream()
                .map(value -> new BigDecimal(value)
                        .setScale(4, RoundingMode.HALF_UP)
                        .doubleValue())
                .collect(Collectors.toList()));
        //统计气
        Map<Integer,Double> qi = new HashMap<>();
        Map<Integer, Double> collectQi = getCollects(equipmentConsumption,formatter,3,consumables.getDateType());
        processVoltageAndCurrentShui(dates,qi,collectQi);
        List<Double> q = new ArrayList<>(qi.values());
        ajaxResult.put("q",q.stream()
                .map(value -> new BigDecimal(value)
                        .setScale(4, RoundingMode.HALF_UP)
                        .doubleValue())
                .collect(Collectors.toList()));
        List<String> hoursStr = new ArrayList<>();
        for (Integer hour : dates) {
            String str = consumables.getDateType().equals("1")?"时":consumables.getDateType().equals("2")?"日":"月";
            hoursStr.add(hour+str);
        }
        ajaxResult.put("hoursStr",hoursStr);
        return AjaxResult.success(ajaxResult);
    }

    private void processVoltageAndCurrentShui(List<Integer> hours, Map<Integer,Double> maps,Map<Integer, Double> collectDian) {
        for (Integer hour : hours) {
            Double v = 0D;
            try {
                v = collectDian.get(hour);
            } catch (Exception e) {
                System.err.println("未知错误：" + e.getMessage());
            }
            addValue(maps, hour, v);
        }
    }

    private void addValue(Map<Integer,Double> list, Integer hour, Double value) {
        Double v1 = -1D;
        if (list.size()!=0) {
            v1=list.get(hour)!=null?list.get(hour):-1D;
        }
        if(value == null){
            list.put(hour, 0D);
            return;
        }
        if(value != -1){
            if(v1 != -1){
                double v2 = v1 + value;
                list.put(hour,v2);
            }
            else{
                list.put(hour, value);
            }
        }
        else{
            if(v1 != -1){
                double v2 = v1 + value+1;
                list.put(hour,v2);
            }
            else {
                list.put(hour, 0D);
            }
        }
    }

    private Map<Integer, Double> getCollects(List<EquipmentConsumptionDto> equipmentConsumption,DateTimeFormatter formatter,Integer energyType,String dateType) {
        Map<Integer, Double> collects = new HashMap<>();
        if(energyType==1){
            List<EquipmentConsumptionDto> collect = equipmentConsumption.stream()
                    .filter(item -> item.getType() == 1 || item.getType() == 2 || item.getType() == 3).collect(Collectors.toList());
            collects=getCollectMap(collect,formatter,dateType);
        }
        if(energyType==2){
            List<EquipmentConsumptionDto> collect = equipmentConsumption.stream()
                    .filter(item -> item.getType() == 7 || item.getType() == 8 || item.getType() == 9 || item.getType() == 10).collect(Collectors.toList());
            collects=getCollectMap(collect,formatter,dateType);
        }
        if(energyType==3){
            List<EquipmentConsumptionDto> collect = equipmentConsumption.stream()
                    .filter(item -> item.getType() == 4 || item.getType() == 5 || item.getType() == 6).collect(Collectors.toList());
            collects=getCollectMap(collect,formatter,dateType);
        }
        return collects;
    }

    private Map<Integer, Double> getCollectMap(List<EquipmentConsumptionDto> equipmentConsumption,DateTimeFormatter formatter,String dateType) {
        Map<Integer, Double> collects = new HashMap<>();
        if(dateType.equals("1")){
            collects=equipmentConsumption.stream()
                    .collect(Collectors.groupingBy(
                            item -> LocalDateTime.parse(item.getCreatedDate(), formatter).getHour(),
                            Collectors.summingDouble(EquipmentConsumptionDto::getEquipmentConPrice) // 计算每个月的总和
                    ));
        }
        if(dateType.equals("2")){
            collects=equipmentConsumption.stream()
                    .collect(Collectors.groupingBy(
                            item -> LocalDateTime.parse(item.getCreatedDate(), formatter).getDayOfMonth(),
                            Collectors.summingDouble(EquipmentConsumptionDto::getEquipmentConPrice) // 计算每个月的总和
                    ));
        }
        if(dateType.equals("3")){
            collects= equipmentConsumption.stream()
                    .collect(Collectors.groupingBy(
                            item -> LocalDateTime.parse(item.getCreatedDate(), formatter).getMonthValue(),
                            Collectors.summingDouble(EquipmentConsumptionDto::getEquipmentConPrice) // 计算每个月的总和
                    ));
        }
        return collects;
    }

    @Override
    public AjaxResult getConsumableShuJuZhanBi(Consumables consumables) {
        List<ConsumablesVo> list = new ArrayList<>();
        //获取定义配置数据
        List<Consumables> consumablesList = consumablesMapper.selectConfiguration(consumables);
        //获取设备id
        List<Long> collect = consumablesList.stream().filter(item -> item.getDeviceId() != null).map(Consumables::getDeviceId).distinct().collect(Collectors.toList());
        if (collect.isEmpty()) {
            return null;
        }
        if (consumables != null && consumables.getEnd() != null) {
            // 月
            if (consumables.getDateType().equals(2)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(consumables.getEnd());
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH) + 1;
                consumables.setEnd(DateUtils.getLastDayOfMonth(year, month));
            }
            consumables.setEnd(DateUtils.changeTheEnd(consumables.getEnd()));
        } else {
            setTimeDimensionDate(consumables);
        }
        //获取设备能源数据
        List<EquipmentConsumptionDto> equipmentConsumption = consumablesMapper.getEquipmentConsumption(consumables, collect);

        //能源水
        double equipmentConsumptionShui = equipmentConsumption.stream().filter(item -> item.getType() == 1 || item.getType() == 2 || item.getType() == 3).mapToDouble(EquipmentConsumptionDto::getEquipmentConPrice).sum();
        //能源电
        double equipmentConsumptionDian = equipmentConsumption.stream().filter(item -> item.getType() == 7 || item.getType() == 8 || item.getType() == 9 || item.getType() == 10).mapToDouble(EquipmentConsumptionDto::getEquipmentConPrice).sum();
        //能源气
        double equipmentConsumptionQi = equipmentConsumption.stream().filter(item -> item.getType() == 4 || item.getType() == 5 || item.getType() == 6).mapToDouble(EquipmentConsumptionDto::getEquipmentConPrice).sum();

        List<CakeVo> cakeVos = new ArrayList<>();
        CakeVo cakeVo = new CakeVo();
        cakeVo.setName("水");
        cakeVo.setValue(String.valueOf(new BigDecimal(equipmentConsumptionShui).setScale(4, RoundingMode.HALF_UP).doubleValue()));
        cakeVos.add(cakeVo);

        CakeVo cakeVodian = new CakeVo();
        cakeVodian.setName("电");
        cakeVodian.setValue(String.valueOf(new BigDecimal(equipmentConsumptionDian).setScale(4, RoundingMode.HALF_UP).doubleValue()));
        cakeVos.add(cakeVodian);

        CakeVo cakeVoqi = new CakeVo();
        cakeVoqi.setName("气");
        cakeVoqi.setValue(String.valueOf(new BigDecimal(equipmentConsumptionQi).setScale(4, RoundingMode.HALF_UP).doubleValue()));
        cakeVos.add(cakeVoqi);
        return AjaxResult.success(cakeVos);
    }

    @Override
    public List<ConsumablesVo> getConsumablePangMing(Consumables consumables) {
        List<ConsumablesVo> list = new ArrayList<>();
        //获取定义配置数据
        List<Consumables> consumablesList = consumablesMapper.selectConfiguration(consumables);
        //获取设备id
        List<Long> collect = consumablesList.stream().filter(item -> item.getDeviceId() != null).map(Consumables::getDeviceId).distinct().collect(Collectors.toList());
        if (collect.isEmpty()) {
            return null;
        }
        if (consumables != null && consumables.getEnd() != null) {
            // 月
            if (consumables.getDateType().equals(2)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(consumables.getEnd());
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH) + 1;
                consumables.setEnd(DateUtils.getLastDayOfMonth(year, month));
            }
            consumables.setEnd(DateUtils.changeTheEnd(consumables.getEnd()));
        } else {
            setTimeDimensionDate(consumables);
        }
        //获取设备能源数据
        List<EquipmentConsumptionDto> equipmentConsumption = consumablesMapper.getEquipmentConsumption(consumables, collect);
        //根据区域来统计
        Map<String, Double> totalByWorkShop = equipmentConsumption.stream()
                .collect(Collectors.groupingBy(
                        dto -> dto.getWorkshopName() + "/" + dto.getFloorName() + "/" + dto.getBuildingName(), // 自定义分组的依据
                        Collectors.summingDouble(EquipmentConsumptionDto::getEquipmentConPrice) // 计算每个组的总和
                ));
        // 获取最大的前五个区域的总消耗价格，并确保最大的总和在前面
        AtomicReference<Integer> i = new AtomicReference<>(1);
        totalByWorkShop.entrySet().stream()
                .sorted(Map.Entry.<String, Double>comparingByValue().reversed()) // 根据值降序排序
                .limit(5)
                .forEach(entry ->{
                    ConsumablesVo consumablesVo = new ConsumablesVo();
                    String[] split = entry.getKey().split("/");
                    consumablesVo.setIndex(i.getAndSet(i.get() + 1));
                    consumablesVo.setWorkshopName(split[0]);
                    consumablesVo.setFloorName(split[1]);
                    consumablesVo.setBuildingName(split[2]);
                    consumablesVo.setUsageAmount(entry.getValue());
                    list.add(consumablesVo);
                });
        return list;
    }

    @Override
    public int addConfiguration(Consumables consumables) {
        consumables.setCreateTime(new Date());
        return consumablesMapper.addConfiguration(consumables);
    }

    @Override
    public List<Consumables> selectConfiguration(Consumables consumables) {
        return consumablesMapper.selectConfiguration(consumables);
    }

    @Override
    public int updateConfiguration(Consumables consumables) {
        return consumablesMapper.updateConfiguration(consumables);
    }

    @Override
    public int deleteConfiguration(Long configurationId) {
        return consumablesMapper.deleteConfiguration(configurationId);
    }

    @Override
    public AjaxResult getConsumableShenQian(Consumables consumables) {
        //获取定义配置数据
        List<Consumables> consumablesList = consumablesMapper.selectConfiguration(consumables);
        //获取设备id
        List<Long> collect = consumablesList.stream().filter(item -> item.getDeviceId() != null).map(Consumables::getDeviceId).distinct().collect(Collectors.toList());
        if (collect.isEmpty()) {
            log.info("没有配置任何设备的标准值");
            return AjaxResult.success();
        }
        if (consumables != null && consumables.getEnd() != null) {
            // 月
            if (consumables.getDateType().equals(2)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(consumables.getEnd());
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH) + 1;
                consumables.setEnd(DateUtils.getLastDayOfMonth(year, month));
            }
            consumables.setEnd(DateUtils.changeTheEnd(consumables.getEnd()));
        } else {
            setTimeDimensionDate(consumables);
        }
        //获取能源数据
        List<EquipmentConsumptionDto> equipmentConsumption = consumablesMapper.getEquipmentConsumption(consumables, collect);

        //获取电，水，气的能源数据
        Map<String, Double> consumablesMap = consumablesList.stream()
                .filter(item -> item.getEnergyType() != null)
                .collect(Collectors.groupingBy(Consumables::getEnergyType, Collectors.summingDouble(Consumables::getUsageAmount)));
        //水的标准值
        Double shui = 0.0D;
        //电的标准值
        Double dian = 0.0D;
        //气的标准值
        Double qi = 0.0D;

        for (Map.Entry<String, Double> entry : consumablesMap.entrySet()) {
            String key = entry.getKey();
            Double value = entry.getValue();
            //水的数据
            if (key.equals("1")) {
                shui = shui+value;
            }
            //电的数据
            if (key.equals("2")) {
                dian = dian+value;
            }
            //气的数据
            if (key.equals("3")) {
                qi = qi+value;
            }
        }
        //能源水
        double equipmentConsumptionShui = equipmentConsumption.stream().filter(item -> item.getType() == 1 || item.getType() == 2 || item.getType() == 3).mapToDouble(EquipmentConsumptionDto::getEquipmentConPrice).sum();
        //能源电
        double equipmentConsumptionDian = equipmentConsumption.stream().filter(item -> item.getType() == 7 || item.getType() == 8 || item.getType() == 9 || item.getType() == 10).mapToDouble(EquipmentConsumptionDto::getEquipmentConPrice).sum();
        //能源气
        double equipmentConsumptionQi = equipmentConsumption.stream().filter(item -> item.getType() == 4 || item.getType() == 5 || item.getType() == 6).mapToDouble(EquipmentConsumptionDto::getEquipmentConPrice).sum();

        AjaxResult ajaxResult = new AjaxResult();
        //计算，用定义的要钱减去能源的实际用钱
        double s = shui - equipmentConsumptionShui;
        double d = dian - equipmentConsumptionDian;
        double q = qi - equipmentConsumptionQi;
        double v = shui + dian + qi;
        double v1 = equipmentConsumptionDian + equipmentConsumptionShui + equipmentConsumptionQi;
        double v2 = v - v1;
        DecimalFormat decimalFormat = new DecimalFormat("#.####");
        ajaxResult.put("shui", decimalFormat.format(s));
        ajaxResult.put("dian", decimalFormat.format(d));
        ajaxResult.put("qi", decimalFormat.format(q));
        ajaxResult.put("v", decimalFormat.format(v2));
        return AjaxResult.success(ajaxResult);
    }
    @Override
    public List<EnergyFlowVo> energyFlowsList(Consumables consumables) {
        List<EnergyFlowVo> energyFlowVos = consumablesMapper.selectEnergyFlowsList(consumables);
        List<SysDictData> dictDatas = DictUtils.getDictCache("energy_region_type");
        if (dictDatas == null || dictDatas.isEmpty()) {
            return energyFlowVos;
        }
        // 使用 Map 来存储现有的状态，避免双重循环
        Map<String, EnergyFlowVo> existingMap = new HashMap<>();
        for (EnergyFlowVo value : energyFlowVos) {
            existingMap.put(value.getEnergyType(), value);
        }
        // 确保每个状态至少有一个对应的
        for (SysDictData dictData : dictDatas) {
            String dictValue = dictData.getDictValue();
            if (!existingMap.containsKey(dictValue)) {
                energyFlowVos.add(new EnergyFlowVo(dictData.getDictLabel(), BigDecimal.ZERO));
            } else {
                EnergyFlowVo existingItem = existingMap.get(dictValue);
                existingItem.setEnergyType(dictData.getDictLabel());
            }
        }
        return energyFlowVos;

    }

    /**
     * 设置时间
     *
     */
    private void setTimeDimensionDate(Consumables consumables) {
        int year = Calendar.getInstance().get(Calendar.YEAR);
        int month = Calendar.getInstance().get(Calendar.MONTH) + 1;
        switch (consumables.getDateType()) {
            case "1":
                consumables.setBegin(DateUtils.getAppointDayTimestamp(0));
                consumables.setEnd(DateUtils.changeTheEnd(new Date()));
                break;
            case "2":
                consumables.setBegin(DateUtils.getAppointMonthTimestamp(0));
                consumables.setEnd(DateUtils.changeTheEnd(DateUtils.getLastDayOfMonth(year, month)));
                break;
            case "3":
                consumables.setBegin(DateUtils.getAppointYearTimestamp(0));
                consumables.setEnd(DateUtils.changeTheEnd(DateUtils.getLastDayOfYear(year)));
                break;
        }
    }
}
